package com.shop2cn.iapi.delivery.testcase;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.google.common.collect.Lists;
import com.shop2cn.iapi.shenqisettlement.parameter.bean.AgentProductBean;
import com.shop2cn.iapi.sqoptrade.parameter.enums.LogisticsTypeEnum;
import com.shop2cn.iapi.sqoptrade.parameter.utill.Utils;
import com.shop2cn.iapi.sqoptrade.resp.TradingServiceResp;
import com.shop2cn.iapi.delivery.parameter.DeliveryInfo;
import com.shop2cn.iapi.delivery.parameter.SqDeliveryReq;
import com.shop2cn.iapi.delivery.parameter.enums.CheckBizResultEnum;
import com.shop2cn.iapi.delivery.parameter.resp.BillNoCheckResult;
import com.shop2cn.iapi.delivery.parameter.resp.DeliveryResp;
import com.shop2cn.iapi.delivery.parameter.resp.DeliveryResult;
import com.shop2cn.iapi.delivery.parameter.resp.ExpectCheckResult;
import com.shop2cn.iapi.delivery.service.DeliveryService;
import com.shop2cn.iapi.delivery.service.SqDeliveryCall;
import com.ymatou.iapi.synctrade.service.TradingSyncService;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.annotation.TestSuite;
import com.ymt.utils.tag.P1;
import com.ymttest.business.service.PayGateWayCallService;
import com.ymttest.business.service.shenqi.DGSQBuildProxyChainCallService;
import com.ymttest.business.service.shenqi.SqTradingCallService;
import com.ymttest.database.sharding.db.ext.model.DeliveryPo;
import com.ymttest.database.sharding.db.sharding.model.OrderPo;
import com.ymttest.database.sharding.db.sharding.model.OrderStatusLogPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.database.sharding.db.sqlwapper.OrderWapper;
import com.ymttest.database.sqlwapper.DefaultWapper;
import com.ymttest.utils.EnvSetup;
import com.ymttest.utils.TestDataManager;

/**
 * 物流发货接口 FreeMaker Template自动生成代码
 */
@TestSuite
public class Ts_sqDelivery {

	private static SqDeliveryReq deliveryReq;
	private static SqDeliveryCall deliveryCall;
	
	private static long autotest_goodsOwnerId = Long.valueOf(EnvSetup
			.getData("autotest_goodsOwnerId"));

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("神器物流发货接口");
	}

	@Before
	public void caseUp() {
		deliveryReq = new SqDeliveryReq();
		deliveryCall = new SqDeliveryCall();
	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(deliveryCall.getOpurl());
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	/**
	 * 
	 * @param expectCheckResultList
	 */
	private void verify(List<ExpectCheckResult> expectCheckResultList) {

		DeliveryResp resp = deliveryCall.getDeliveryResp();

		List<DeliveryResult> billNoCheckResults = resp.getDeliveryResults();

		int i = 0;

		for (ExpectCheckResult expectcheckResultInfo : expectCheckResultList) {

			BillNoCheckResult checkResult = billNoCheckResults.get(i);

			Logger.verifyEquals(expectcheckResultInfo.isBizSuccess(),
					checkResult.isBizSuccess(), "校验BizSuccess");

			if (checkResult.isBizSuccess()) {

				// 交易订单状态数据
				verifyOrderStatus(expectcheckResultInfo.getDeliveryInfo(),
						deliveryReq.getGoodsOwnerId(), false);
			}

			Logger.verifyEquals(expectcheckResultInfo.isMicroShopOrder(),
					checkResult.isMicroShopOrder(), "校验microShopOrder");

			Logger.verifyEquals(expectcheckResultInfo.isValidation(),
					checkResult.isValidation(), "校验validation");

			Logger.verifyEquals(expectcheckResultInfo.getBizCode(),
					checkResult.getBizCode(), "校验bizCode");

			Logger.verifyEquals(expectcheckResultInfo.getBizMsg(),
					checkResult.getBizMsg(), "校验bizMsg");

			Logger.verifyEquals(expectcheckResultInfo.getLogisticsType(),
					checkResult.getLogisticsType(), "校验logisticsType");

			Logger.verifyEquals(expectcheckResultInfo.getOrderStatus(),
					checkResult.getOrderStatus(), "校验订单状态");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getBillNo(), checkResult.getBillNo(), "校验billNo");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getOrderId(), checkResult.getOrderId(), "校验orderId");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getMobile(), checkResult.getMobile(), "校验mobile");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getDeliverySection(), checkResult.getDeliverySection(),
					"校验deliverySection");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getDeliverySource(), checkResult.getDeliverySource(),
					"校验deliverySource");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getRealDeliveryArea(), checkResult.getRealDeliveryArea(),
					"校验realDeliveryArea");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getYmtExpressCode(), checkResult.getYmtExpressCode(),
					"校验ymtExpressCode");

			i++;

		}
	}

//	/**
//	 * 校验自动确认收货时间操作详情表（auto_receive_opt_detail）
//	 */
//	private void verifyAutoReceiveDetail(long orderId,
//			boolean isShippedByXlobo, boolean isFreeze) {
//
//		AutoReceiveOptDetailPo actual = new OrderShardingWapper()
//				.selectAutoReceiveOptDetailByOrderId(orderId);
//
//		Logger.comment(String.format(
//				"验证自动确认收货时间操作详情表（auto_receive_opt_detail）  orderId: %s",
//				orderId));
//
//		Logger.verifyEquals(true,
//				Utils.calcTimeSpanMin(actual.getAddTime()) < 2,
//				"验证数据库AddTime跟系统当前时间差为2分钟内");
//		Logger.verifyEquals(true,
//				Utils.calcTimeSpanMin(actual.getUpdateTime()) < 2,
//				"验证数据库UpdateTime跟系统当前时间差为2分钟内");
//
//		int bizType = 1;
//
//		if (!isShippedByXlobo) {
//			bizType = 2;
//		}
//
//		Logger.verifyEquals(orderId, actual.getOrderId(), "验证数据库OrderId");
//
//		Logger.verifyEquals(bizType, actual.getBizType(), "验证数据库BizType");
//
//		Logger.verifyEquals(isFreeze, actual.getFreeze(), "验证数据库Freeze");
//
//		if (!isFreeze) {
//			Logger.verifyEquals(true,
//					Utils.calcTimeSpanMin(actual.getUnfreezeTime()) < 2,
//					"验证数据库UnfreezeTime跟系统当前时间差为2分钟内");
//
//		} else {
//			Logger.verifyEquals(null, actual.getUnfreezeTime(),
//					"验证数据库UnfreezeTime跟系统当前时间差为2分钟内");
//		}
//
//		verifyAutoReceive(orderId, isFreeze);
//	}
//
//	/**
//	 * 校验自动确认收货时间操作表（auto_receive_opt）
//	 */
//	private void verifyAutoReceive(long orderId, boolean isFreeze) {
//
//		// 自动确认收货时间操作表（auto_receive_opt）
//		AutoReceiveOptPo autoReceiveOptPo = new OrderShardingWapper()
//				.selectAutoReceiveOptByOrderId(orderId);
//
//		Logger.comment(String.format(
//				"验证自动确认收货时间操作表（auto_receive_opt）  orderId: %s", orderId));
//
//		Logger.verifyEquals(true,
//				Utils.calcTimeSpanMin(autoReceiveOptPo.getAddTime()) < 2,
//				"验证数据库AddTime跟系统当前时间差为2分钟内");
//		Logger.verifyEquals(true,
//				Utils.calcTimeSpanMin(autoReceiveOptPo.getUpdateTime()) < 2,
//				"验证数据库UpdateTime跟系统当前时间差为2分钟内");
//
//		Logger.verifyEquals(orderId, autoReceiveOptPo.getOrderId(),
//				"验证数据库OrderId");
//		Logger.verifyEquals(isFreeze, autoReceiveOptPo.getFreeze(),
//				"验证数据库Freeze");
//
//		Logger.verifyEquals(true,
//				Utils.calcTimeSpanMin(autoReceiveOptPo.getFreezeTime()) < 2,
//				"验证数据库FreezeTime跟系统当前时间差为2分钟内");
//
//		/*
//		 * Logger.verifyEquals(null, autoReceiveOptPo.getExpectReceiveTime(),
//		 * "验证数据库ExpectReceiveTime");
//		 */
//
//	}

	/**
	 * 校验订单表状态，单主状态操作日志表
	 */
	private void verifyOrderStatus(DeliveryInfo info, long sellerId,
			boolean isShippedByXlobo) {

		OrderShardingWapper orderShardingWapper = new OrderShardingWapper();

		long orderId = info.getOrderId();

		// 订单表(order)
		OrderPo ymtOrders = orderShardingWapper.selectOrderbyOrderId(orderId);

		Logger.comment(String.format("验证订单表(order)表 orderId: %s", orderId));

		Logger.verifyEquals(3, ymtOrders.getOrderStatus(), "验证orderStatus");

		Logger.verifyEquals(isShippedByXlobo, ymtOrders.getXloboDelivery(),
				"验证xloboDelivery");

		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(ymtOrders.getDeliveryTime()) < 2,
				"验证数据库deliveryTime跟系统当前时间差为2分钟内");

		// 订单主状态操作日志表(order_status_log)
		OrderStatusLogPo orderStatusLogPo = orderShardingWapper
				.selectOrderStatusLogByOrderId(orderId);

		Logger.comment("验证订单主状态操作日志表(order_status_log)");

		Logger.verifyEquals("发货", orderStatusLogPo.getMemo(), "验证数据库Memo");
		Logger.verifyEquals(3, orderStatusLogPo.getOrderStatus(),
				"验证数据库OrderStatus");

		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(orderStatusLogPo.getAddTime()) < 2,
				"验证数据库AddTime跟系统当前时间差为2分钟内");

		Logger.verifyEquals(orderId, orderStatusLogPo.getOrderId(),
				"验证数据库OrderId");
		Logger.verifyEquals(sellerId, orderStatusLogPo.getOperator(),
				"验证数据库Operator");

//		if (ymtOrders.getLogisticsType() == 7 && !ymtOrders
//				.getDomesticDelivery()) {
//			verifyAutoReceiveDetail(orderId, false, !ymtOrders
//					.getDomesticDelivery().equals(true));
//		}

		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		verifyDeliveryDb(info, sellerId, ymtOrders.getShenqiLogisticsType());
	}

	/**
	 * 校验 mysql delivery 表
	 * 
	 * @param info
	 */
	private void verifyDeliveryDb(DeliveryInfo info, long sellerId,
			int logisticsType) {

		long orderId = info.getOrderId();

		DeliveryPo actualDeliveryPo = new OrderWapper()
				.selectDeliveryByOrderIdAndSection(orderId, info.getDeliverySection());
		
//		int deliveryPoSize = new OrderWapper().selectDeliverySizeByOrderId(orderId);

		Logger.comment("校验 delivery 表数据");

		Logger.verifyEquals(info.getYmtExpressCode(),
				actualDeliveryPo.getYmtExpressCode(), "验证数据库YmtExpressCode");

		Logger.verifyEquals(false, actualDeliveryPo.getOfficalLogistics(),
				"验证数据库OfficalLogistics");

		Logger.verifyEquals(Utils.zeroIfNull(info.getRealDeliveryArea()),
				actualDeliveryPo.getRealDeliveryArea(), "验证数据库RealDeliveryArea");

		Logger.verifyEquals(orderId, actualDeliveryPo.getOrderId(),
				"验证数据库OrderId");

		Logger.verifyEquals(sellerId, actualDeliveryPo.getSellerId(),
				"验证数据库SellerId");

		Logger.verifyEquals(logisticsType, actualDeliveryPo.getLogisticsType(),
				"验证数据库LogisticsType");

		Logger.verifyEquals(false, actualDeliveryPo.getDeleted(),
				"验证数据库Deleted");

		Logger.verifyEquals(info.getDeliverySource(),
				actualDeliveryPo.getSource(), "验证数据库Source");
		
		if (logisticsType == LogisticsTypeEnum.PackageDelivery.getCode()
                && info.getDeliverySection() == 3)
			Logger.verifyEquals(true, actualDeliveryPo.getSourceTrack(),
					"验证数据库SourceTrack");			
		else
			Logger.verifyEquals(false, actualDeliveryPo.getSourceTrack(),
					"验证数据库SourceTrack");

		Logger.verifyEquals(info.getBillNo(), actualDeliveryPo.getBillNo(),
				"验证数据库BillNo");

		Logger.verifyEquals(info.getDeliverySection(),
				actualDeliveryPo.getSection(), "验证数据库Section");

		Logger.verifyEquals(info.getMobile(), actualDeliveryPo.getMobile(),
				"验证数据库Mobile");

		if (DeliveryService.isWriteSqlServer) {

			verifySqlServerDb(info, sellerId, logisticsType);
		}

	}

	/**
	 * 校验 sql Ymt_BillCodeSummary Ymt_BillCodeSummaryToOrders 表
	 * 
	 * @param info
	 */
	@SuppressWarnings("rawtypes")
	private void verifySqlServerDb(DeliveryInfo info, Long sellerId,
			int logisticsType) {

		Long orderId = info.getOrderId();

		String sqlString = String
				.format("SELECT * FROM dbo.Ymt_BillCodeSummary x INNER JOIN dbo.Ymt_BillCodeSummaryToOrders "
						+ "y ON x.billCodeSummaryID = y.BillCodeSummaryID where orderid=%s",
						orderId);

		Logger.comment("校验 Ymt_BillCodeSummary , Ymt_BillCodeSummaryToOrders");

		List<Map> res = new DefaultWapper().executeSql(sqlString);

		if (CollectionUtils.isEmpty(res)) {

			Logger.comment("sql server Ymt_BillCodeSummary 数据为空 ");

			Logger.fail(new Exception("sql server Ymt_BillCodeSummary 数据为空"));

		}

		Map actualBillCodeSummary = res.get(0);

		Logger.verifyEquals(sellerId.intValue(),
				(Integer) actualBillCodeSummary.get("SellerID"),
				"验证数据库SellerID");

		Logger.verifyEquals(info.getBillNo(),
				(String) actualBillCodeSummary.get("billCode"), "验证数据库billCode");

		/*
		 * Logger.verifyEquals(logisticsType, (Integer)
		 * actualBillCodeSummary.get("DeliverType"), "验证数据库DeliverType");
		 */

		Logger.verifyEquals(info.getYmtExpressCode(),
				(String) actualBillCodeSummary.get("InnerExpressCode"),
				"验证数据库InnerExpressCode");

		Logger.verifyEquals(false,
				(Boolean) actualBillCodeSummary.get("IsOfficalLogistic"),
				"验证数据库IsOfficalLogistic");

		Logger.verifyEquals(
				info.getDeliverySection() == 3
						|| info.getDeliverySection() == 2,
				(Boolean) actualBillCodeSummary.get("IsChinaDeliver"),
				"验证数据库IsChinaDeliver");

		Logger.verifyEquals(info.getDeliverySection() == 2 ? 1 : null,
				(Integer) actualBillCodeSummary.get("Tranship"),
				"验证数据库Tranship");

		Logger.verifyEquals(false,
				(Boolean) actualBillCodeSummary.get("IsDeleted"),
				"验证数据库IsDeleted");

		Logger.verifyEquals(logisticsType,
				(Integer) actualBillCodeSummary.get("CatalogStatus"),
				"验证数据库CatalogStatus");

		Logger.verifyEquals(Utils.zeroIfNull(info.getRealDeliveryArea()) == 1,
				actualBillCodeSummary.get("ShipByHK"), "验证数据库ShipByHK");

		Logger.verifyEquals(orderId.intValue(),
				(Integer) actualBillCodeSummary.get("OrderID"), "验证数据库Orde1rID");

	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_sqDelivery_001() {
		Logger.start(true, "神器发货订单，部分发货后，可以多次发货");
		try {

			// 创建订单
			Logger.comment("前置数据准备");

			AgentProductBean productBean = DGSQBuildProxyChainCallService
					.createProxychain((int) autotest_goodsOwnerId, 0, false);
			TradingServiceResp placeOrderResp = SqTradingCallService
					.placeOrder(productBean, BigDecimal.ZERO);

			long userId = placeOrderResp.getUserId();
			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();
			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			// 支付订单
			Long thirdTradingId = SqTradingCallService.payOrder(userId,
					placeOrderResp.getTradingId());

			// 支付网关支付回调交易
			PayGateWayCallService.DGSQNotifyCall(
					String.valueOf(thirdTradingId),
					totalPrice.subtract(BigDecimal.ZERO).toString(),
					(int) userId, BigDecimal.ZERO.toPlainString());

			TradingSyncService.getSyncResult(orderId);
			Thread.sleep(5000);

			// 接单
			SqTradingCallService
					.sellerAcceptOrder(autotest_goodsOwnerId, orderId);
			TradingSyncService.getSyncResult(orderId);

			Logger.comment("前置数据准备结束");

			DeliveryInfo dInfo = new DeliveryInfo();

			dInfo.setOrderId(orderId);

			dInfo.setBillNo(TestDataManager.getRandomNum(13));

			// 发货节点、1国际段,2转运段,3国内段
			dInfo.setDeliverySection(3);
			dInfo.setDeliverySource(1);

			dInfo.setExpressName("sf");
			dInfo.setYmtExpressCode("Y013");
			
			dInfo.setPartialDeliveryStatus(1);

			// dInfo.setRealDeliveryArea(realDeliveryArea);

			deliveryReq.setDeliveryInfos(Lists.newArrayList(dInfo));
			deliveryReq.setGoodsOwnerId(autotest_goodsOwnerId);

			deliveryCall.setData(deliveryReq);
			deliveryCall.callService();
			
			// 修改运单号，再次发货
			deliveryReq.getDeliveryInfos().forEach(item -> {
				item.setBillNo(TestDataManager.getRandomNum(13));
			});
			deliveryCall.callService();

			Logger.verifyEquals(deliveryCall.getSuccess(), true, "校验IsSuccess");

			List<ExpectCheckResult> list = new ArrayList<ExpectCheckResult>();

			deliveryReq
					.getDeliveryInfos()
					.forEach(
							item -> {

								ExpectCheckResult expectCheckResult = new ExpectCheckResult(
										item);

								expectCheckResult
										.setBizCode(CheckBizResultEnum.passed
												.getCode());
								expectCheckResult
										.setBizMsg(null);

								expectCheckResult.setBizSuccess(true);
								expectCheckResult.setValidation(true);

								expectCheckResult.setLogisticsType(999);
								expectCheckResult.setMicroShopOrder(false);
								expectCheckResult.setOrderStatus(3);

								list.add(expectCheckResult);

							});
			
			Thread.sleep(5000);

			verify(list);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
}